/**
 * 格式化工具函数
 * 提供各种数据格式化功能
 */

/**
 * 时间格式化相关
 */
export const timeFormat = {
  /**
   * 格式化时间为相对时间
   */
  relative(date: Date | string | number): string {
    const now = new Date()
    const target = new Date(date)
    const diff = now.getTime() - target.getTime()
    
    const seconds = Math.floor(diff / 1000)
    const minutes = Math.floor(seconds / 60)
    const hours = Math.floor(minutes / 60)
    const days = Math.floor(hours / 24)
    const months = Math.floor(days / 30)
    const years = Math.floor(months / 12)

    if (seconds < 60) return '刚刚'
    if (minutes < 60) return `${minutes}分钟前`
    if (hours < 24) return `${hours}小时前`
    if (days < 30) return `${days}天前`
    if (months < 12) return `${months}个月前`
    return `${years}年前`
  },

  /**
   * 格式化时间为聊天时间显示
   */
  chatTime(date: Date | string | number): string {
    const target = new Date(date)
    const now = new Date()
    const today = new Date(now.getFullYear(), now.getMonth(), now.getDate())
    const yesterday = new Date(today.getTime() - 24 * 60 * 60 * 1000)
    const targetDate = new Date(target.getFullYear(), target.getMonth(), target.getDate())

    const timeStr = target.toLocaleTimeString('zh-CN', { 
      hour: '2-digit', 
      minute: '2-digit',
      hour12: false 
    })

    if (targetDate.getTime() === today.getTime()) {
      return timeStr
    } else if (targetDate.getTime() === yesterday.getTime()) {
      return `昨天 ${timeStr}`
    } else if (target.getFullYear() === now.getFullYear()) {
      return target.toLocaleDateString('zh-CN', { 
        month: 'numeric', 
        day: 'numeric' 
      }) + ` ${timeStr}`
    } else {
      return target.toLocaleDateString('zh-CN') + ` ${timeStr}`
    }
  },

  /**
   * 格式化持续时间
   */
  duration(milliseconds: number): string {
    const seconds = Math.floor(milliseconds / 1000)
    const minutes = Math.floor(seconds / 60)
    const hours = Math.floor(minutes / 60)

    if (hours > 0) {
      return `${hours}:${(minutes % 60).toString().padStart(2, '0')}:${(seconds % 60).toString().padStart(2, '0')}`
    } else {
      return `${minutes}:${(seconds % 60).toString().padStart(2, '0')}`
    }
  },

  /**
   * 格式化为标准时间字符串
   */
  standard(date: Date | string | number): string {
    return new Date(date).toLocaleString('zh-CN', {
      year: 'numeric',
      month: '2-digit',
      day: '2-digit',
      hour: '2-digit',
      minute: '2-digit',
      second: '2-digit',
      hour12: false
    })
  }
}

/**
 * 文件大小格式化
 */
export const fileFormat = {
  /**
   * 格式化文件大小
   */
  size(bytes: number): string {
    if (bytes === 0) return '0 B'
    
    const k = 1024
    const sizes = ['B', 'KB', 'MB', 'GB', 'TB']
    const i = Math.floor(Math.log(bytes) / Math.log(k))
    
    return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]
  },

  /**
   * 获取文件扩展名
   */
  extension(filename: string): string {
    return filename.slice((filename.lastIndexOf('.') - 1 >>> 0) + 2).toLowerCase()
  },

  /**
   * 获取文件类型图标
   */
  typeIcon(filename: string): string {
    const ext = this.extension(filename)
    const iconMap: Record<string, string> = {
      // 图片
      jpg: 'image', jpeg: 'image', png: 'image', gif: 'image', webp: 'image', svg: 'image',
      // 文档
      pdf: 'pdf', doc: 'word', docx: 'word', xls: 'excel', xlsx: 'excel', ppt: 'powerpoint', pptx: 'powerpoint',
      // 压缩包
      zip: 'archive', rar: 'archive', '7z': 'archive', tar: 'archive', gz: 'archive',
      // 音频
      mp3: 'audio', wav: 'audio', flac: 'audio', aac: 'audio',
      // 视频
      mp4: 'video', avi: 'video', mkv: 'video', mov: 'video', wmv: 'video',
      // 代码
      js: 'code', ts: 'code', html: 'code', css: 'code', json: 'code', xml: 'code',
      // 文本
      txt: 'text', md: 'text', log: 'text'
    }
    return iconMap[ext] || 'file'
  }
}

/**
 * 数字格式化
 */
export const numberFormat = {
  /**
   * 格式化数字为千分位
   */
  thousands(num: number): string {
    return num.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',')
  },

  /**
   * 格式化数字为简短形式
   */
  short(num: number): string {
    if (num < 1000) return num.toString()
    if (num < 10000) return (num / 1000).toFixed(1) + 'K'
    if (num < 1000000) return Math.floor(num / 1000) + 'K'
    if (num < 10000000) return (num / 1000000).toFixed(1) + 'M'
    return Math.floor(num / 1000000) + 'M'
  },

  /**
   * 格式化百分比
   */
  percentage(num: number, decimals: number = 1): string {
    return (num * 100).toFixed(decimals) + '%'
  },

  /**
   * 格式化货币
   */
  currency(num: number, currency: string = '¥'): string {
    return currency + this.thousands(num)
  }
}

/**
 * 文本格式化
 */
export const textFormat = {
  /**
   * 截断文本
   */
  truncate(text: string, length: number, suffix: string = '...'): string {
    if (text.length <= length) return text
    return text.slice(0, length) + suffix
  },

  /**
   * 首字母大写
   */
  capitalize(text: string): string {
    return text.charAt(0).toUpperCase() + text.slice(1).toLowerCase()
  },

  /**
   * 驼峰转换
   */
  camelCase(text: string): string {
    return text.replace(/[-_\s]+(.)?/g, (_, char) => char ? char.toUpperCase() : '')
  },

  /**
   * 短横线转换
   */
  kebabCase(text: string): string {
    return text.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase()
  },

  /**
   * 移除HTML标签
   */
  stripHtml(html: string): string {
    return html.replace(/<[^>]*>/g, '')
  },

  /**
   * 转义HTML
   */
  escapeHtml(text: string): string {
    const div = document.createElement('div')
    div.textContent = text
    return div.innerHTML
  },

  /**
   * 高亮关键词
   */
  highlight(text: string, keyword: string, className: string = 'highlight'): string {
    if (!keyword) return text
    const regex = new RegExp(`(${keyword})`, 'gi')
    return text.replace(regex, `<span class="${className}">$1</span>`)
  },

  /**
   * 格式化手机号
   */
  phone(phone: string): string {
    const cleaned = phone.replace(/\D/g, '')
    if (cleaned.length === 11) {
      return cleaned.replace(/(\d{3})(\d{4})(\d{4})/, '$1 $2 $3')
    }
    return phone
  },

  /**
   * 脱敏处理
   */
  mask: {
    phone: (phone: string): string => {
      return phone.replace(/(\d{3})\d{4}(\d{4})/, '$1****$2')
    },
    email: (email: string): string => {
      const [name, domain] = email.split('@')
      if (name.length <= 2) return email
      return name.slice(0, 2) + '***' + name.slice(-1) + '@' + domain
    },
    idCard: (idCard: string): string => {
      return idCard.replace(/(\d{6})\d{8}(\d{4})/, '$1********$2')
    }
  }
}

/**
 * URL格式化
 */
export const urlFormat = {
  /**
   * 添加协议前缀
   */
  addProtocol(url: string, protocol: string = 'https'): string {
    if (!/^https?:\/\//i.test(url)) {
      return `${protocol}://${url}`
    }
    return url
  },

  /**
   * 获取域名
   */
  getDomain(url: string): string {
    try {
      return new URL(this.addProtocol(url)).hostname
    } catch {
      return ''
    }
  },

  /**
   * 构建查询字符串
   */
  buildQuery(params: Record<string, any>): string {
    const query = new URLSearchParams()
    Object.entries(params).forEach(([key, value]) => {
      if (value !== null && value !== undefined && value !== '') {
        query.append(key, String(value))
      }
    })
    return query.toString()
  },

  /**
   * 解析查询字符串
   */
  parseQuery(search: string): Record<string, string> {
    const params = new URLSearchParams(search.startsWith('?') ? search.slice(1) : search)
    const result: Record<string, string> = {}
    params.forEach((value, key) => {
      result[key] = value
    })
    return result
  }
}

/**
 * 颜色格式化
 */
export const colorFormat = {
  /**
   * 十六进制转RGB
   */
  hexToRgb(hex: string): { r: number; g: number; b: number } | null {
    const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex)
    return result ? {
      r: parseInt(result[1], 16),
      g: parseInt(result[2], 16),
      b: parseInt(result[3], 16)
    } : null
  },

  /**
   * RGB转十六进制
   */
  rgbToHex(r: number, g: number, b: number): string {
    return '#' + [r, g, b].map(x => {
      const hex = x.toString(16)
      return hex.length === 1 ? '0' + hex : hex
    }).join('')
  },

  /**
   * 生成随机颜色
   */
  random(): string {
    return '#' + Math.floor(Math.random() * 16777215).toString(16).padStart(6, '0')
  },

  /**
   * 根据字符串生成颜色
   */
  fromString(str: string): string {
    let hash = 0
    for (let i = 0; i < str.length; i++) {
      hash = str.charCodeAt(i) + ((hash << 5) - hash)
    }
    const color = (hash & 0x00FFFFFF).toString(16).toUpperCase()
    return '#' + '00000'.substring(0, 6 - color.length) + color
  }
}

/**
 * 便捷导出函数
 */
export const formatRelativeTime = timeFormat.relative
export const formatChatTime = timeFormat.chatTime
export const formatFileSize = fileFormat.size
export const formatNumber = numberFormat.thousands
export const formatDistanceToNow = timeFormat.relative

// 导出所有格式化函数
export default {
  time: timeFormat,
  file: fileFormat,
  number: numberFormat,
  text: textFormat,
  url: urlFormat,
  color: colorFormat
}